/* Copyright (c) 2003-2007 Caleb Doise
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;


namespace SharpScraps.Win32
{

    public static class WindowHelper
    {
        public static IntPtr GetTaskbarWindow()
        {            
            return USER32.FindWindow("Shell_TrayWnd", null);
        } // GetTaskbarWindow

        public static bool IsTaskbarWindow(IntPtr hWnd)
        {
            IntPtr shellWnd = USER32.GetShellWindow();            

            string windowText = USER32Helper.GetWindowText(hWnd);				

            if (!USER32.IsWindowVisible(hWnd) ||
                windowText == null ||
                windowText.Length == 0 ||
                USER32.GetParent(hWnd) != IntPtr.Zero ||
                hWnd == shellWnd)
            {
                return false;
            }            

            RECT r;
            USER32.GetWindowRect(hWnd, out r);
            if ((r.Width <= 0) || (r.Height <= 0))
                return false;
			
		    return true;
        } // IsTaskbarWindow


        public static IntPtr[] GetTaskbarWindows()
        {
            IntPtr[] windows = USER32Helper.EnumChildWindows(USER32.GetDesktopWindow());

            List<IntPtr> windowList = new List<IntPtr>(windows);
            int co = windowList.Count - 1;
            while (co >= 0)
            {
                IntPtr hwnd = (IntPtr)windowList[co];
                if (!IsTaskbarWindow(hwnd))
                    windowList.RemoveAt(co);				

                co--;
            }

            return windowList.ToArray();
        } // GetTaskbarWindows



        public static void RefreshWindow(IntPtr hWnd)
        {                        
            USER32.InvalidateRect(hWnd, IntPtr.Zero, true);
            USER32.UpdateWindow(hWnd);
            USER32.RedrawWindow(
                hWnd, 
                IntPtr.Zero, 
                IntPtr.Zero, 
                USER32.RedrawWindowConstants.RDW_FRAME | 
                    USER32.RedrawWindowConstants.RDW_INVALIDATE | 
                    USER32.RedrawWindowConstants.RDW_UPDATENOW | 
                    USER32.RedrawWindowConstants.RDW_ALLCHILDREN);
        } // RefreshWindow    



        public static IntPtr GetTopLevelParentWindow(IntPtr hWnd)
        {
            IntPtr parentWnd = USER32.GetParent(hWnd);
            if (parentWnd != USER32.GetDesktopWindow() && parentWnd != USER32.GetShellWindow())
            {               
                while (parentWnd != USER32.GetDesktopWindow() &&  parentWnd != USER32.GetShellWindow() && parentWnd != IntPtr.Zero)
                {
                    hWnd = parentWnd;
                    parentWnd = USER32.GetParent(hWnd);
                }
            }

            return hWnd;
        } // GetTopLevelParentWindow



        public static Int32 GetProcessIDForWindow(IntPtr hWnd)
        {
            Int32 processID;
            USER32.GetWindowThreadProcessId(hWnd, out processID);

            return processID;
        } // GetProcessIDForHwnd


        public static IntPtr[] GetTopLevelWindowsForProcessID(UInt32 processID)
        {
            IntPtr[] topLevelWindows = USER32Helper.EnumChildWindows(USER32.GetDesktopWindow());

            List<IntPtr> processWindows = new List<IntPtr>();

            foreach (IntPtr hWnd in topLevelWindows)
            {
                if (GetProcessIDForWindow(hWnd) == processID)
                    processWindows.Add(hWnd);
            }

            return processWindows.ToArray();
        } // GetTopLevelWindowsForProcessID


        public static IntPtr[] GetTaskbarWindowsForProcessID(UInt32 processID)
        {
            IntPtr[] topLevelWindows = USER32Helper.EnumChildWindows(USER32.GetDesktopWindow());

            List<IntPtr> processWindows = new List<IntPtr>();

            foreach (IntPtr hWnd in topLevelWindows)
            {
                if ((GetProcessIDForWindow(hWnd) == processID) && WindowHelper.IsTaskbarWindow(hWnd))
                    processWindows.Add(hWnd);
            }

            return processWindows.ToArray();
        } // GetTopLevelWindowsForProcessID


        /// <summary>
        /// FindControlForWindowHandle tries to find the Windows Forms control 
        /// given an hWnd.
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        public static Control FindControlForWindowHandle(IntPtr hWnd)
        {
            // If the window is in a different process, we won't be able to
            // retrieve the Control.
            if (System.Diagnostics.Process.GetCurrentProcess().Id != GetProcessIDForWindow(hWnd))
                return null;

            foreach (Form form in Application.OpenForms)
            {
                Control foundControl = RecursivelyFindControlByWindowHandle(form, hWnd);
                if (foundControl != null)
                    return foundControl;
            }

            return null;
        }

        private static Control RecursivelyFindControlByWindowHandle(Control parent, IntPtr hWnd)
        {
            if (hWnd == parent.Handle)
                return parent;

            foreach (Control control in parent.Controls)
            {
                Control foundControl = RecursivelyFindControlByWindowHandle(control, hWnd);
                if (foundControl != null)
                    return foundControl;
            }

            return null;
        }


    } // class WindowHelper   


} // namespace namespace SharpScraps.Win32